package com.jl.card.provider.jl2g;

import com.jl.card.Card;
import com.jl.card.ISOConstants;
import com.jl.card.ISecurityOperation;
import com.jl.card.parse.SimpleAnalyse;
import com.jl.card.util.APDUUtil;

public class JL2GSecurityOperation implements ISecurityOperation {

	private Card card;

	private final static String[] allTypes = new String[] { "PIN1", "PIN2",
			"ADM1" };

	public JL2GSecurityOperation(Card card) {
		this.card = card;
	}

	@Override
	public boolean verify(int type, byte[] value) {
		byte[] cmd = APDUUtil.make((byte) 0xa0, (byte) 0x20, (byte) 0x00,
				(byte) (type & 0xFF), paddingPin(value));
		byte[] res = card.plainAPDU(cmd);
		int sw = SimpleAnalyse.sw(res);
		return sw == ISOConstants.RC_OK;
	}

	@Override
	public boolean change(int type, byte[] old, byte[] value) {
		byte[] temp = new byte[16];
		System.arraycopy(paddingPin(old), 0, temp, 0, 8);
		System.arraycopy(paddingPin(value), 0, temp, 8, 8);

		byte[] cmd = APDUUtil.make((byte) 0xa0, (byte) 0x24, (byte) 0x00,
				(byte) (type & 0xFF), temp);
		byte[] res = card.plainAPDU(cmd);
		int sw = SimpleAnalyse.sw(res);
		return sw == ISOConstants.RC_OK;
	}

	@Override
	public boolean enable(int type, byte[] value) {
		byte[] cmd = APDUUtil.make((byte) 0xa0, (byte) 0x28, (byte) 0x00,
				(byte) (type & 0xFF), paddingPin(value));
		byte[] res = card.plainAPDU(cmd);
		int sw = SimpleAnalyse.sw(res);
		return sw == ISOConstants.RC_OK;
	}

	@Override
	public boolean disable(int type, byte[] value) {
		byte[] cmd = APDUUtil.make((byte) 0xa0, (byte) 0x26, (byte) 0x00,
				(byte) (type & 0xFF), paddingPin(value));
		byte[] res = card.plainAPDU(cmd);
		int sw = SimpleAnalyse.sw(res);
		return sw == ISOConstants.RC_OK;
	}

	@Override
	public boolean unblock(int type, byte[] puk, byte[] value) {
		byte[] temp = new byte[16];
		System.arraycopy(paddingPin(puk), 0, temp, 0, 8);
		System.arraycopy(paddingPin(value), 0, temp, 8, 8);

		byte[] cmd = APDUUtil.make((byte) 0xa0, (byte) 0x2c, (byte) 0x00,
				(byte) (type & 0xFF), temp);
		byte[] res = card.plainAPDU(cmd);
		int sw = SimpleAnalyse.sw(res);
		return sw == ISOConstants.RC_OK;
	}

	@Override
	public int getTypeCode(String type) {
		type = type.toUpperCase().trim();
		if (type.equals("PIN1")) {
			return 0x01;
		}
		if (type.equals("PIN2")) {
			return 0x02;
		}
		if (type.equals("ADM1")) {
			return 0x0a;
		}
		return 0;
	}

	private byte[] paddingPin(byte[] value) {
		byte[] _value = new byte[8];
		for (int i = 0; i < 8; i++) {
			_value[i] = (byte) 0xFF;
		}
		System.arraycopy(value, 0, _value, 0, value.length > 8 ? 8
				: value.length);
		return _value;
	}

	@Override
	public String[] getAllTypes() {
		return allTypes;
	}

}
